package com.ionehe.group.common.file.oss.file;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.BucketInfo;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.ionehe.group.common.file.FileServer;
import com.ionehe.group.common.file.configure.FileServerConfiguration;
import com.ionehe.group.common.file.configure.FileVendors;
import com.ionehe.group.common.file.enums.ContentTypeEnum;
import com.ionehe.group.common.file.exception.FileException;
import com.ionehe.group.common.file.oss.flags.OssKeyFlags;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Copyright (c) 2021 ionehe.com
 * Date: 2020/9/25
 * Time: 上午9:30
 *
 * @author 2020年 <a href="mailto:a@ionehe.com">秀</a>
 * 【oss客户端】
 */
@Slf4j
public class FileServerImpl implements FileServer {
    private final String bucket;
    private OSS ossClient;
    private final String endpoint;

    public FileServerImpl(FileServerConfiguration conf) {
        log.info("Oss client init ...");

        Map<String, Object> vendor = (Map<String, Object>) conf.getVendors().get(FileVendors.oss);

        this.endpoint = OssKeyFlags.FLAG_ENDPOINT.get(vendor);
        this.bucket = OssKeyFlags.FLAG_BUCKET.get(vendor);
        String secret = OssKeyFlags.FLAG_SECRET.get(vendor);
        String access = OssKeyFlags.FLAG_ACCESS.get(vendor);

        try {
            // 创建OSSClient实例
            this.ossClient = new OSSClientBuilder().build(endpoint, access, secret);

            // 创建bucket
            BucketInfo bucketInfo = ossClient.getBucketInfo(bucket);
            if (Objects.isNull(bucketInfo) || Objects.isNull(bucketInfo.getBucket())) {
                ossClient.createBucket(bucket);
                log.info("Oss client create bucket {} success!", bucket);
            }
            log.info("Oss client init success!");
        } catch (Exception e) {
            log.error("Oss client init error! endpoint:{}, bucket:{}, cause:{}", endpoint, bucket, Throwables.getStackTraceAsString(e));
        }
    }

    @Override
    @Deprecated
    public String write(String fileName, MultipartFile file) {
        log.info("FileServer[]write[]start!");
        if (StrUtil.isBlank(fileName) || Objects.isNull(file) || file.getSize() <= 0) {
            log.warn("FileServer[]write[]parameter illegal!");
            throw new FileException("parameter illegal");
        }

        try {
            long start = System.currentTimeMillis();
            // 上传文件
            ObjectMetadata meta = new ObjectMetadata();
            String ext = FileUtil.extName(fileName).toUpperCase();
            String contentType = ContentTypeEnum.valueOf(ext).getCentType();
            meta.setContentType(contentType);
            ossClient.putObject(bucket, fileName, file.getInputStream(), meta);
            long end = System.currentTimeMillis();
            log.info("耗时:{}毫秒", end - start);
            log.info("FileServer[]write[]success!");
            return getFileUrl(fileName);
        } catch (Exception e) {
            log.error("FileServer[]write[]error! cause:{}", Throwables.getStackTraceAsString(e));
            return null;
        }
    }

    @Override
    public String write(String fileName, File file) {
        log.info("FileServer[]write[]start!");
        if (StrUtil.isBlank(fileName) || Objects.isNull(file) || FileUtil.size(file) <= 0) {
            log.warn("FileServer[]write[]parameter illegal!");
            throw new FileException("parameter illegal");
        }

        try {
            long start = System.currentTimeMillis();
            // 上传文件
            ObjectMetadata meta = new ObjectMetadata();
            String ext = FileUtil.extName(fileName).toUpperCase();
            String contentType = ContentTypeEnum.valueOf(ext).getCentType();
            meta.setContentType(contentType);
            ossClient.putObject(bucket, fileName, file, meta);
            long end = System.currentTimeMillis();
            log.info("耗时:{}毫秒", end - start);
            log.info("FileServer[]write[]success!");
            return getFileUrl(fileName);
        } catch (Exception e) {
            log.error("FileServer[]write[]error! cause:{}", Throwables.getStackTraceAsString(e));
            return null;
        }
    }

    @Override
    public boolean delete(String fileName) {
        return delete(Lists.newArrayList(fileName));
    }

    @Override
    public boolean delete(List<String> fileNameList) {
        log.info("FileServer[]delete[]start! fileNameList:{}", fileNameList);

        try {
            String e = "";

            if (endpoint.startsWith("http")) e = endpoint.replace("http://", "");
            if (endpoint.startsWith("https")) e = endpoint.replace("https://", "");

            String basePath = bucket + "." + e + "/";

            List<String> delList = new ArrayList<>();

            for (String fn : fileNameList) {
                if (!fn.contains(basePath)) {
                    continue;
                }
                if (fn.startsWith("http")) fn = fn.replace("http://" + basePath, "");

                if (fn.startsWith("https")) fn = fn.replace("https://" + basePath, "");

                delList.add(fn);
            }

            ossClient.deleteObjects(new DeleteObjectsRequest(bucket).withKeys(delList));
            return true;
        } catch (Exception e) {
            log.info("FileServer[]batchDelete[]error! fileNames:{}, cause:{}", fileNameList, Throwables.getStackTraceAsString(e));
            return false;
        }
    }

    @Override
    public InputStream getObject(String fileName) {
        log.info("FileServer[]getObject[]start! fileName:{}", fileName);
        if (StrUtil.isBlank(fileName)) {
            log.warn("FileServer[]write[]file is empty!");
            throw new FileException("file name can not be null");
        }

        try {
            long start = System.currentTimeMillis();
            OSSObject ossObject = ossClient.getObject(bucket, fileName);
            long end = System.currentTimeMillis();
            log.info("耗时:{}毫秒", end - start);
            log.info("FileServer[]getObject[]success!");
            return ossObject.getObjectContent();
        } catch (Exception e) {
            log.error("FileServer[]getObject[]bucketName:{}, fileName:{} error! cause:{}",
                    bucket, fileName, Throwables.getStackTraceAsString(e));
            return null;
        }
    }

    @Override
    public String getFileUrl(String fileName) {
        OSSObject ossObject = ossClient.getObject(bucket, fileName);
        return ossObject.getResponse().getUri();
    }
}
